/***************************************************************************
 *   Copyright (C) 2008 by JBox systems
 *   gabi@shaargiora.co.il
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 ***************************************************************************/

#include "controller.h"
#include "memory.h"
#include "log.h"
#include "config.h"
#include "ftpdownloader.h"
#include "httpdownloader.h"

Controller::Controller(QObject *parent):
	QObject(parent) {
	connectController();
}

Controller::~Controller() {

}

bool sortVersionByInstallerType(Version i, Version j) {
	if (CONFIG.silentFirst()) {
		if (i.silent()) return false;
	} else {
		if (j.silent()) return false;
	}
	return true;
}

void Controller::apply(std::vector<Version> p_versions, bool download_only) {
	versions = p_versions;
	std::sort(versions.begin(), versions.end(), sortVersionByInstallerType);
	m_download_only = download_only;
	m_abort = false;
	applyNext();
}

void Controller::connectController() {
	connect(&ftp_downloader, SIGNAL(downloadFinished(bool)), this, SLOT(install(bool)));
	connect(&ftp_downloader, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(dataReadProgress(int, int)));
	connect(&ftp_downloader, SIGNAL(currentDownloadFilename(QString)), this, SIGNAL(currentProcess(QString)));
	connect(&http_downloader, SIGNAL(downloadFinished(bool)), this, SLOT(install(bool)));
	connect(&http_downloader, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(dataReadProgress(int, int)));
	connect(&http_downloader, SIGNAL(currentDownloadFilename(QString)), this, SIGNAL(currentProcess(QString)));
}

void Controller::applyNext() {
	// Finished
	if (versions.size() == 0) {
		emit finished(false);
		return;
	}
	// Aborted
	if (m_abort) {
		emit aborted();
		return;
	}
	// Process next version
	versions.front().reload();
	currentVersion = versions.front();
	versions.erase(versions.begin(), versions.begin()+1);

	LOG("Applying " << currentVersion.name())
	// Start download
	if (currentVersion.hasInstaller() and !m_download_only) // Have an installer and not set to only download.
		install();
	else	if (currentVersion.hasUrl()) // No installer, but can download one.
		download(currentVersion);
	else // Have neither installer, neither place to download from . skip.
		applyNext();
}

void Controller::abort() {
	m_abort = true;
	if (download_type == FTP)
		ftp_downloader.cancelDownload();
	else
		http_downloader.cancelDownload();
}

void Controller::install(bool error) {
	if (m_download_only) {
		LOG("Set to download only. not installing")
		applyNext();
		return;
		// FIXME recursion. better way without recursion ?
	}

	if (error and CONFIG.haltOnDownloadError()) {
		emit finished(true);
		return;
	}

	if (!error and !m_abort) {
		currentVersion.findInstallerFile();
		emit status(QString((std::string("Proceeding to install ") + currentVersion.name() + " " + currentVersion.version()).c_str()));
		installer.install(currentVersion);
		emit status(QString("Installer finished with exit code: ") + QString::number(installer.lastCode()));;
		if ((installer.lastCode() != 0) and CONFIG.haltOnInstallError()) {
			emit finished(true);
			return;
		}
	}
	applyNext();
}

void Controller::download(Version &version) {

	QUrl url(version.url().c_str());
	if(url.scheme().toLower() == "ftp") {
		download_type = FTP;
		ftp_downloader.downloadFile(version.url(), version.path());
	} else { //assume http/https
		download_type = HTTP;
		http_downloader.downloadFile(version.url(), version.path());
	}

	// Notify what is being downloaded
	emit status(QString("Downloading %1 %2").arg(QString(version.name().c_str())).arg(QString(version.version().c_str())));
}
